home *** CD-ROM | disk | FTP | other *** search
/ Electronic Clipper 1995 April / Electronic Clipper 1995-04.iso / pc / pc_users / ideasrc / setup / pviewer / pictkids.c < prev    next >
Text File  |  1993-04-17  |  54KB  |  1,293 lines

  1.  
  2. // ---------------------------------------------------------------------
  3. //
  4. // PictKids.c - Picture Viewer - QuickTime for Windows
  5. //
  6. //              Version 1.0
  7. //
  8. //              (c) 1988-1992 Apple Computer, Inc. All Rights Reserved.
  9. //
  10. // ---------------------------------------------------------------------
  11.  
  12.  
  13. // Includes
  14. // --------
  15.    #define NOMINMAX
  16.    #include <Windows.H>               // Required by Windows
  17.    #include <stdlib.h>                // Required for abs function
  18.  
  19.    #include <qtole.h>                 // Interface to qtole dll
  20.    #include <qtw.h>                   // Interface to QuickTime
  21.    #include "common.h"                // Interface to common.c
  22.  
  23.    #include "viewer.h"                // Interface to *.c files
  24.    #include "viewer.hr"               // Defines used in *.rc files
  25.    #include "picture.h"               // Interface to picture window
  26.                                       // child window processing
  27.  
  28.  
  29. // Constants
  30. // -----------------------
  31.    #define BANNER_TEXT_HEIGHT      9   // Banner text height in points
  32.    #define TEXT_EXTRA_SPACING      1   // Extra spacing in number text
  33.  
  34. // Message-Persistent Data
  35. // -----------------------
  36.    static struct                       // Hungarian notation: g
  37.      {WORD        wScrollBarWidth;     // Vertical scroll bar width
  38.       WORD        wScrollBarHeight;    // Horizontal scroll bar height
  39.       WORD        wBannerBarHeight;    // Banner bar height
  40.       WORD        wZoomWndWidth;       // Width of zoom scroll bar window
  41.       WORD        wMinWndHeight;       // Minimum height of window
  42.       HBITMAP     hbmpGrowBox;         // Grow box bitmap
  43.       BOOL        bLimitGrowBoxResize; // Flag to turn on max resize limits
  44.                                        // using grow box
  45.       POINT       ptMaxGrowBoxResize;  // Max size for grow box resizing
  46.  
  47.       RECT        rcResizeRect;        // Maximized wnd grow box resize rect
  48.       POINT       ptCursorOffset;      // Offset of cursor from edge of window
  49.                                        // used during maximized wnd grow box resize
  50.      } g;
  51.  
  52.  
  53. // Exported callback function
  54. // ----------------------------
  55.    LONG __export CALLBACK PictureBannerWndProc  (HWND, UINT, WPARAM, LPARAM);
  56.  
  57. // Internal Function Declarations
  58. // ------------------------------
  59.    static VOID    NEAR UpdateScrollingParms    (HWND, NPPICTUREDATA, LPRECT);
  60.    static HBITMAP NEAR GetGrowBoxBitmap        (HDC, NPPICTUREDATA);
  61.    static VOID    NEAR DrawTheFrameRect        (LPRECT);
  62.  
  63.  
  64. // Function: ResizeKids - Resizes the child windows whenever the picture
  65. //                        window is resized
  66. // --------------------------------------------------------------------
  67. // Parameters: HWND    hwndPicture       Handle of picture window
  68. //             WORD    wClientWidth      Width of client rect
  69. //             WORD    wClientHeight     Height of client rect
  70. //
  71. // Returns:    0L
  72. // --------------------------------------------------------------------
  73.    VOID FAR ResizeKids
  74.                 ( HWND hwndPicture, WORD wClientWidth, WORD wClientHeight )
  75.  
  76.      {NPPICTUREDATA   pPictureData;    // -> picture data struct
  77.       RECT            rcPicture;       // Picture rect in picture coordinates
  78.       HDWP            hdwp;            // Handle to defer wnd pos struct
  79.       int             xBrdr;           // Width of non resizable border
  80.       int             yBrdr;           // Height of non resizable border
  81.  
  82.    // Note: All the extra terms involving xBrdr and yBrdr are used to make
  83.    // the control boundaries match up correctly without heavy lines 
  84.    // appearing between the controls
  85.  
  86.       xBrdr = GetSystemMetrics( SM_CXBORDER );
  87.       yBrdr = GetSystemMetrics( SM_CYBORDER );
  88.  
  89.       if( !(pPictureData =
  90.                          (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  91.          {CommonTellUser( ViewerQueryResources(),
  92.                    VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  93.           return;
  94.          }
  95.  
  96.       if( ( hdwp = BeginDeferWindowPos( 5 )) &&
  97.               // Zoom window. This control has a constant size
  98.           ( hdwp = DeferWindowPos( hdwp, pPictureData->zsZoomScroll.hwnd,
  99.                      NULL,
  100.                      -xBrdr,
  101.                      wClientHeight - g.wScrollBarHeight + yBrdr,
  102.                      g.wZoomWndWidth,
  103.                      g.wScrollBarHeight, 
  104.                      SWP_NOZORDER )) &&
  105.               // Banner bar. This control has a constant height
  106.           ( hdwp = DeferWindowPos( hdwp, pPictureData->hwndBanner, 
  107.                      NULL,
  108.                      0,
  109.                      0,
  110.                      wClientWidth,
  111.                      g.wBannerBarHeight,
  112.                      SWP_NOZORDER )) && 
  113.               // Vertical scroll bar. This control has a constant width
  114.           ( hdwp = DeferWindowPos( hdwp, pPictureData->spmsVScroll.hwnd,
  115.                      NULL, 
  116.                      wClientWidth - g.wScrollBarWidth + xBrdr,
  117.                      g.wBannerBarHeight - yBrdr,
  118.                      g.wScrollBarWidth,
  119.                      wClientHeight - g.wScrollBarHeight
  120.                                       - g.wBannerBarHeight + 3 * yBrdr,
  121.                      SWP_NOZORDER )) && 
  122.               // Horizontal scroll bar. This control has a constant height
  123.           ( hdwp = DeferWindowPos( hdwp, pPictureData->spmsHScroll.hwnd,
  124.                      NULL, 
  125.                      g.wZoomWndWidth - 2 * xBrdr,
  126.                      wClientHeight - g.wScrollBarHeight + yBrdr,
  127.                      wClientWidth - g.wZoomWndWidth - 
  128.                                    g.wScrollBarWidth + 4 * xBrdr,
  129.                      g.wScrollBarHeight,
  130.                      SWP_NOZORDER )))
  131.          {EndDeferWindowPos( hdwp );
  132.          } 
  133.       else
  134.          {    // Zoom window. This control has a constant size
  135.           MoveWindow( pPictureData->zsZoomScroll.hwnd,
  136.                      -xBrdr, wClientHeight - g.wScrollBarHeight + yBrdr,
  137.                              g.wZoomWndWidth, g.wScrollBarHeight, TRUE );
  138.  
  139.               // Banner bar. This control has a constant height
  140.           MoveWindow( pPictureData->hwndBanner, 0, 0,
  141.                                   wClientWidth, g.wBannerBarHeight, TRUE );
  142.  
  143.               // Vertical scroll bar. This control has a constant width
  144.           MoveWindow( pPictureData->spmsVScroll.hwnd,
  145.                wClientWidth - g.wScrollBarWidth + xBrdr,
  146.                   g.wBannerBarHeight - yBrdr, g.wScrollBarWidth,
  147.                         wClientHeight - g.wScrollBarHeight -
  148.                                    g.wBannerBarHeight + 3 * yBrdr, TRUE );
  149.  
  150.               // Horizontal scroll bar. This control has a constant height
  151.           MoveWindow( pPictureData->spmsHScroll.hwnd,
  152.                   g.wZoomWndWidth - 2 * xBrdr,
  153.                        wClientHeight - g.wScrollBarHeight + yBrdr,
  154.                      wClientWidth - g.wZoomWndWidth -
  155.                            g.wScrollBarWidth + 4 * xBrdr,
  156.                                                g.wScrollBarHeight, TRUE );
  157.          }
  158.  
  159.       pPictureData->rcGrowBox.left = wClientWidth  - 
  160.                                            g.wScrollBarWidth + 2 * xBrdr;
  161.       pPictureData->rcGrowBox.top  = wClientHeight -
  162.                                            g.wScrollBarHeight + 2 * yBrdr;
  163.       pPictureData->rcGrowBox.right  = wClientWidth;
  164.       pPictureData->rcGrowBox.bottom = wClientHeight;
  165.  
  166.       rcPicture.left   = rcPicture.top = 0;
  167.       rcPicture.right  = wClientWidth;
  168.       rcPicture.bottom = wClientHeight;
  169.       PictureRectFromClient( &rcPicture );
  170.  
  171.       UpdateScrollingParms( hwndPicture, pPictureData, &rcPicture );
  172.  
  173.         // Force these to get painted now to avoid long delay while
  174.         // waiting for the picture to be painted. This improves the 
  175.         // appearance of the window during resizing
  176.       UpdateWindow( pPictureData->zsZoomScroll.hwnd );
  177.       UpdateWindow( pPictureData->hwndBanner );
  178.       UpdateWindow( pPictureData->spmsHScroll.hwnd );
  179.       UpdateWindow( pPictureData->spmsVScroll.hwnd );
  180.  
  181.       return;
  182.      }
  183.  
  184.  
  185. // Function: CreateViewerKids - Creates the child windows for the picture
  186. //                              window
  187. // --------------------------------------------------------------------
  188. // Parameters: HWND           hwndPicture     Handle of picture window
  189. //             NPPICTUREDATA  pPictureData    -> to picture data struct
  190. //
  191. // Returns:    LONG           0l if OK
  192. // --------------------------------------------------------------------
  193.    LONG FAR CreateViewerKids( HWND hwndPicture, NPPICTUREDATA pPictureData )
  194.  
  195.      {WORD    wIDError;     // Resource error string id
  196.  
  197.       g.wScrollBarWidth  = (WORD) GetSystemMetrics( SM_CXVSCROLL );
  198.       g.wScrollBarHeight = (WORD) GetSystemMetrics( SM_CYHSCROLL );
  199.       g.wBannerBarHeight = (WORD) GetSystemMetrics( SM_CYMENU );
  200.       g.wMinWndHeight    = (WORD) ( GetSystemMetrics( SM_CYCAPTION ) +
  201.                               g.wBannerBarHeight + g.wScrollBarHeight + 
  202.                                 3 * GetSystemMetrics( SM_CYVSCROLL ));
  203.  
  204.  
  205.       wIDError = VIEWER_STRING_NOMEMORY;
  206.       if( !( pPictureData->spmsHScroll.hwnd =
  207.                     CreateWindow( "scrollbar", NULL,
  208.                            WS_CHILD | WS_VISIBLE | SBS_HORZ,
  209.                                0, 0, 0, 0, hwndPicture,
  210.                                     (HMENU) PICTURE_HORZ_SCROLL,
  211.                                           ViewerQueryInstance(), NULL )))
  212.          {goto Failed;
  213.          }
  214.  
  215.       if( !(pPictureData->spmsVScroll.hwnd =
  216.                     CreateWindow( "scrollbar", NULL,
  217.                            WS_CHILD | WS_VISIBLE | SBS_VERT,
  218.                                0, 0, 0, 0, hwndPicture,
  219.                                     (HMENU) PICTURE_VERT_SCROLL,
  220.                                           ViewerQueryInstance(), NULL )))
  221.          {goto Failed;
  222.          }
  223.  
  224.            // Try initial width. This may be adjusted during create processing
  225.       if( !( pPictureData->zsZoomScroll.hwnd =
  226.                     CreateWindow( PICTURE_ZOOM_CLASS, NULL,
  227.                            WS_CHILD | WS_VISIBLE | WS_BORDER,
  228.                              0, 0, 6 * GetSystemMetrics( SM_CXHSCROLL ),
  229.                                  g.wScrollBarHeight, hwndPicture,
  230.                                      (HMENU) PICTURE_ZOOM_SCROLL,
  231.                                            ViewerQueryInstance(), NULL )))
  232.          {goto Failed;
  233.          }
  234.       else   // Set the global variable here because dimensions may have
  235.              // been adjusted. Use the query because GetClientRect() won't 
  236.              // work until after first call to MoveWindow() and we need 
  237.              // width before then.
  238.          {g.wZoomWndWidth = ViewerQueryZoomWndWidth();
  239.          }
  240.  
  241.       if( !( pPictureData->hwndBanner =
  242.                     CreateWindow( PICTURE_BANNER_CLASS, NULL,
  243.                            WS_CHILD | WS_VISIBLE,
  244.                             0, 0, 0, 0, hwndPicture,
  245.                                     (HMENU) PICTURE_BANNER,
  246.                                           ViewerQueryInstance(), NULL )))
  247.          {goto Failed;
  248.          }
  249.            // this window does nothing so disable it
  250.       EnableWindow( pPictureData->hwndBanner, FALSE );
  251.  
  252.       return 0L;
  253.  
  254.  Failed:
  255.       CommonTellUser( ViewerQueryResources(), wIDError, NULL, MB_OK );
  256.       return MAKELONG( wIDError, 0 );
  257.      }
  258.  
  259.  
  260. // Function: ZoomPicture - Resizes the Picture to the input width and
  261. //                         height
  262. // --------------------------------------------------------------------
  263. // Parameters: HWND         hwndPicture     Handle of Picture window
  264. //             WORD         wZoomIndex      Index of desired zoom
  265. //
  266. // Returns:    LONG         0L if successful
  267. // --------------------------------------------------------------------
  268.    LONG FAR ZoomPicture( HWND hwndPicture, WORD wZoomIndex )
  269.  
  270.      {NPPICTUREDATA  pPictureData;      // -> picture data struct
  271.       RECT           rcMaxPicture;      // Current max picture display area
  272.       WORD           wZoomMult;         // Zoom multiplier factor
  273.  
  274.  
  275.       if( !(pPictureData =
  276.                          (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  277.          {CommonTellUser( ViewerQueryResources(),
  278.                    VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  279.           return VIEWER_STRING_NOPICDATA;
  280.          }
  281.  
  282.       if( pPictureData->zsZoomScroll.wCurZoomIndex == wZoomIndex )
  283.           return 0L;
  284.  
  285.       pPictureData->rcCurPictureRect.left = 0;
  286.       pPictureData->rcCurPictureRect.top  = 0;
  287.  
  288.       wZoomMult = ViewerQueryZoomMultiplier( wZoomIndex );
  289.       pPictureData->rcCurPictureRect.right = 
  290.                MulDiv( pPictureData->idImageInfo.width, wZoomMult, 100 );
  291.       pPictureData->rcCurPictureRect.bottom = 
  292.                MulDiv( pPictureData->idImageInfo.height, wZoomMult, 100 );
  293.  
  294.    // Get client rect
  295.       GetClientRect( hwndPicture, &rcMaxPicture );
  296.  
  297.    // Convert to Picture coordinates
  298.       PictureRectFromClient( &rcMaxPicture );
  299.  
  300.    // This routine also offsets rcCurPictureRect when necessary
  301.       UpdateScrollingParms( hwndPicture, pPictureData, &rcMaxPicture );
  302.  
  303.    // Update buckle ...
  304.       pPictureData->zsZoomScroll.wCurZoomIndex = wZoomIndex;
  305.       if( IsWindowVisible( pPictureData->zsZoomScroll.hwnd ))
  306.           SendMessage( pPictureData->zsZoomScroll.hwnd,
  307.                              WM_ZOOM_MOVEBUCKLE, (WPARAM) wZoomIndex, 0L );
  308.  
  309.    // ... and paint
  310.       InvalidateRect( hwndPicture, NULL, TRUE);
  311.  
  312.       if( pPictureData->hwndGetInfo )
  313.           SendMessage( pPictureData->hwndGetInfo,
  314.                                           WM_INFO_CURRENTSIZE, 0, 0L );
  315.  
  316.       return 0L;
  317.      }
  318.  
  319.  
  320. // Function: ClientRectFromPicture - Returns the client rect in client
  321. //                                   coordinates that corresponds to the
  322. //                                   input picture rect in picture coords.
  323. // --------------------------------------------------------------------
  324. // Parameters: LPRECT       lprc     -> Picture rect on input
  325. //
  326. // Returns:    VOID         lprc     -> Client rect on output
  327. // --------------------------------------------------------------------
  328.    VOID FAR ClientRectFromPicture( LPRECT lprc )
  329.  
  330.      {
  331.       lprc->right  -= lprc->left;
  332.       lprc->bottom -= lprc->top;
  333.       lprc->left = lprc->top = 0;
  334.  
  335.       lprc->right  += g.wScrollBarWidth - 
  336.                                   GetSystemMetrics( SM_CXBORDER );
  337.       lprc->bottom += g.wScrollBarHeight + g.wBannerBarHeight -
  338.                                   GetSystemMetrics( SM_CYBORDER );
  339.  
  340.       return;
  341.      }
  342.  
  343. // Function: PictureRectFromClient - Returns the maximum picture rect
  344. //                                   in picture coordinates corresponding
  345. //                                   to the input client rect in
  346. //                                   client coords
  347. // --------------------------------------------------------------------
  348. // Parameters: LPRECT       lprc   -> Client rect on input
  349. //
  350. // Returns:    VOID         lprc   -> Max Picture rect on output
  351. // --------------------------------------------------------------------
  352.    VOID FAR PictureRectFromClient( LPRECT lprc )
  353.  
  354.      {
  355.       lprc->right  -= lprc->left;
  356.       lprc->bottom -= lprc->top;
  357.  
  358.       lprc->left = lprc->top = 0;
  359.       lprc->right  -= g.wScrollBarWidth - 
  360.                                   GetSystemMetrics( SM_CXBORDER );
  361.       lprc->bottom -= g.wScrollBarHeight + g.wBannerBarHeight -
  362.                                   GetSystemMetrics( SM_CYBORDER );
  363.  
  364.       return;
  365.      }
  366.  
  367. // Function: ClientToPicture - Converts from client to picture coordinates
  368. // --------------------------------------------------------------------
  369. // Parameters: LPPOINT       lppt     -> points
  370. //             WORD          wNum     Number of points to convert
  371. //
  372. // Returns:    VOID
  373. // --------------------------------------------------------------------
  374.    VOID FAR ClientToPicture( LPPOINT lppt, WORD wNum )
  375.  
  376.      {WORD    i;       // Counter
  377.  
  378.       for(i=0; i < wNum; i++, lppt++)
  379.          lppt->y -= g.wBannerBarHeight;
  380.  
  381.       return;
  382.      }
  383.  
  384. // Function: PictureToClient - Converts from picture to client coordinates
  385. // --------------------------------------------------------------------
  386. // Parameters: LPPOINT       lppt     -> points
  387. //             WORD          wNum     number of points to convert
  388. //
  389. // Returns:    VOID
  390. // --------------------------------------------------------------------
  391.    VOID FAR PictureToClient( LPPOINT lppt, WORD wNum )
  392.  
  393.      {WORD    i;       // Counter
  394.  
  395.       for(i=0; i < wNum; i++, lppt++)
  396.          lppt->y += g.wBannerBarHeight;
  397.  
  398.       return;
  399.      }
  400.  
  401. // Function: SetMinMaxInfo - Processes the picture window
  402. //                           WM_GETMINMAXINFO message
  403. // --------------------------------------------------------------------
  404. // Parameters: MINMAXINFO FAR*    lpmmi   -> to minmaxinfo struct
  405. //
  406. // Returns:    LONG               always 0L
  407. // --------------------------------------------------------------------
  408.    LONG FAR SetMinMaxInfo( MINMAXINFO FAR* lpmmi )
  409.  
  410.      {
  411.       lpmmi->ptMinTrackSize.x = g.wZoomWndWidth +
  412.                                     5 * GetSystemMetrics( SM_CXHSCROLL );
  413.       lpmmi->ptMinTrackSize.y = g.wMinWndHeight;
  414.  
  415.       if( g.bLimitGrowBoxResize )
  416.          {lpmmi->ptMaxTrackSize = g.ptMaxGrowBoxResize;
  417.          }
  418.  
  419.       return 0L;
  420.      }
  421.  
  422.  
  423. // Function: UpdateScrollingParms - Update the scroll bar parameters after
  424. //                                  size of picture is changed
  425. // --------------------------------------------------------------------
  426. // Parameters: HWND           hwndPicture      Handle of picture window
  427. //             NPPICTUREDATA  pPictureData     -> picture data struct
  428. //             LPRECT         lprcMaxPicture   -> to to picture display
  429. //                                             area of wnd
  430. //
  431. // Returns:    VOID
  432. // --------------------------------------------------------------------
  433.    static VOID NEAR UpdateScrollingParms( HWND hwndPicture,
  434.                        NPPICTUREDATA pPictureData, LPRECT lprcMaxPicture )
  435.  
  436.      {WORD      wCurPictWidth;     // Current picture width
  437.       WORD      wCurPictHeight;    // Current picture height
  438.       WORD      wOldMax;           // Previous max scroll value
  439.       WORD      wDisplayWidth;     // Display width, i.e. area available
  440.                                    // for display of picture
  441.       WORD      wDisplayHeight;    // Display height
  442.  
  443.  
  444.       wCurPictWidth  = pPictureData->rcCurPictureRect.right -
  445.                                        pPictureData->rcCurPictureRect.left;
  446.       wCurPictHeight = pPictureData->rcCurPictureRect.bottom -
  447.                                        pPictureData->rcCurPictureRect.top;
  448.       wDisplayWidth  = lprcMaxPicture->right - lprcMaxPicture->left;
  449.       wDisplayHeight = lprcMaxPicture->bottom - lprcMaxPicture->top;
  450.  
  451.          // leave these fixed
  452.       pPictureData->spmsHScroll.wCurLine = g.wScrollBarWidth;
  453.       pPictureData->spmsVScroll.wCurLine = g.wScrollBarHeight;
  454.  
  455.          // Adjust these for size of window
  456.       pPictureData->spmsHScroll.wCurPage = wDisplayWidth - 1;
  457.       pPictureData->spmsVScroll.wCurPage = wDisplayHeight - 1;
  458.  
  459.          // Set horizontal scrollbar parms
  460.       if( wDisplayWidth >= wCurPictWidth )
  461.          {pPictureData->spmsHScroll.wCurPos  = 0;
  462.           pPictureData->spmsHScroll.wCurMax  = 0;
  463.           EnableWindow( pPictureData->spmsHScroll.hwnd, FALSE );
  464.          }
  465.       else
  466.          {wOldMax = pPictureData->spmsHScroll.wCurMax;
  467.           pPictureData->spmsHScroll.wCurMax  =
  468.                                          wCurPictWidth - wDisplayWidth;
  469.         // Scale current position for new display area
  470.           if( wOldMax > 0 )
  471.              pPictureData->spmsHScroll.wCurPos =
  472.                       MulDiv( pPictureData->spmsHScroll.wCurPos,
  473.                               pPictureData->spmsHScroll.wCurMax, wOldMax );
  474.           else
  475.              pPictureData->spmsHScroll.wCurPos = 0;
  476.  
  477.           EnableWindow( pPictureData->spmsHScroll.hwnd, TRUE );
  478.  
  479.           SetScrollRange( pPictureData->spmsHScroll.hwnd, SB_CTL,
  480.                             0, pPictureData->spmsHScroll.wCurMax, FALSE );
  481.           SetScrollPos( pPictureData->spmsHScroll.hwnd, SB_CTL,
  482.                                 pPictureData->spmsHScroll.wCurPos, TRUE );
  483.          }
  484.  
  485.          // Set vertical scrollbar parms
  486.       if( wDisplayHeight >= wCurPictHeight )
  487.          {pPictureData->spmsVScroll.wCurPos  = 0;
  488.           pPictureData->spmsVScroll.wCurMax  = 0;
  489.           EnableWindow( pPictureData->spmsVScroll.hwnd, FALSE );
  490.          }
  491.       else
  492.          {wOldMax = pPictureData->spmsVScroll.wCurMax;
  493.           pPictureData->spmsVScroll.wCurMax =
  494.                                             wCurPictHeight - wDisplayHeight;
  495.         // Scale current position for new display area
  496.           if( wOldMax > 0 )
  497.               pPictureData->spmsVScroll.wCurPos =
  498.                       MulDiv( pPictureData->spmsVScroll.wCurPos,
  499.                               pPictureData->spmsVScroll.wCurMax, wOldMax );
  500.           else
  501.               pPictureData->spmsVScroll.wCurPos = 0;
  502.  
  503.           EnableWindow( pPictureData->spmsVScroll.hwnd, TRUE );
  504.  
  505.           SetScrollRange( pPictureData->spmsVScroll.hwnd, SB_CTL,
  506.                             0, pPictureData->spmsVScroll.wCurMax, FALSE );
  507.           SetScrollPos( pPictureData->spmsVScroll.hwnd, SB_CTL,
  508.                                 pPictureData->spmsVScroll.wCurPos, TRUE );
  509.          }
  510.  
  511.  
  512.    // Define ->rcCurPictureRect.   The point (0, 0) is always the Upper-Left
  513.    // corner of the display area. Therefore, rcCur.. .left and .top are
  514.    // negative if the picture is scrolled.
  515.       pPictureData->rcCurPictureRect.left =
  516.                                - ((int) pPictureData->spmsHScroll.wCurPos);
  517.       pPictureData->rcCurPictureRect.top  =
  518.                                - ((int) pPictureData->spmsVScroll.wCurPos);
  519.       pPictureData->rcCurPictureRect.right =
  520.                      pPictureData->rcCurPictureRect.left + wCurPictWidth;
  521.       pPictureData->rcCurPictureRect.bottom =
  522.                      pPictureData->rcCurPictureRect.top  + wCurPictHeight;
  523.  
  524.       return;
  525.      }
  526.  
  527.  
  528. // Function: ProcessHorzScroll - Process horizontal scroll bar messages
  529. // --------------------------------------------------------------------
  530. // Parameters: HWND    hwndPicture       Handle of picture window
  531. //             WORD    wScrollCode       Scroll code as defined in windows.h
  532. //             int     nCurBoxPos        Current position of scroll box
  533. //
  534. // Returns:    LONG    0L if OK
  535. // --------------------------------------------------------------------
  536.    LONG FAR ProcessHorzScroll
  537.                      (HWND hwndPicture, WORD wScrollCode, int nCurBoxPos )
  538.  
  539.      {NPPICTUREDATA   pPictureData;    // -> picture data struct
  540.       int             nPosition;       // Temp scroll position
  541.       WORD            wWidth;          // Picture width
  542.       int             nToScroll;       // Amount to scroll
  543.       RECT            rcPictArea;      // Picture rect in client coordinates
  544.  
  545.  
  546.       if( !(pPictureData =
  547.                          (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  548.          {CommonTellUser( ViewerQueryResources(),
  549.                    VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  550.           return VIEWER_STRING_NOPICDATA;
  551.          }
  552.  
  553.       if( !IsWindowEnabled( pPictureData->spmsHScroll.hwnd ))
  554.           return 0L;
  555.  
  556.       nPosition = pPictureData->spmsHScroll.wCurPos;
  557.  
  558.       switch( wScrollCode )
  559.          {case SB_PAGERIGHT:
  560.               nPosition += pPictureData->spmsHScroll.wCurPage;
  561.               break;
  562.           case SB_LINERIGHT:
  563.               nPosition += pPictureData->spmsHScroll.wCurLine;
  564.               break;
  565.           case SB_PAGELEFT:
  566.               nPosition -= pPictureData->spmsHScroll.wCurPage;
  567.               break;
  568.           case SB_LINELEFT:
  569.               nPosition -= pPictureData->spmsHScroll.wCurLine;
  570.               break;
  571.           case SB_LEFT:
  572.               nPosition = 0;
  573.               break;
  574.           case SB_RIGHT:
  575.               nPosition = pPictureData->spmsHScroll.wCurMax;
  576.               break;
  577.           case SB_THUMBPOSITION:
  578.               nPosition = (WORD) nCurBoxPos;
  579.               break;
  580.           default:
  581.               break;
  582.          }
  583.  
  584.       nPosition = min( max( 0, nPosition ),
  585.                                  (int) pPictureData->spmsHScroll.wCurMax );
  586.       if( nPosition != (int) pPictureData->spmsHScroll.wCurPos )
  587.          {nToScroll = nPosition - pPictureData->spmsHScroll.wCurPos;
  588.           pPictureData->spmsHScroll.wCurPos = nPosition;
  589.  
  590.           wWidth = pPictureData->rcCurPictureRect.right -
  591.                                        pPictureData->rcCurPictureRect.left;
  592.           pPictureData->rcCurPictureRect.left  = -nPosition;
  593.           pPictureData->rcCurPictureRect.right = -nPosition + wWidth;
  594.  
  595.           SetScrollPos( pPictureData->spmsHScroll.hwnd, SB_CTL,
  596.                                 pPictureData->spmsHScroll.wCurPos, TRUE );
  597.  
  598.             // Get picture rect in picture coordinates
  599.           GetClientRect( hwndPicture, &rcPictArea );
  600.           PictureRectFromClient( &rcPictArea);
  601.             // Convert to client coordinates for ScrollWindow
  602.           PictureToClient( (LPPOINT) &rcPictArea, 2 );
  603.  
  604.           if( ((WORD) abs( nToScroll )) <
  605.                                       pPictureData->spmsHScroll.wCurPage )
  606.              {UpdateWindow( hwndPicture );
  607.               ScrollWindow( hwndPicture, -nToScroll, 0,
  608.                                                &rcPictArea, &rcPictArea );
  609.              }
  610.           else
  611.              InvalidateRect( hwndPicture, &rcPictArea, TRUE );
  612.  
  613.           UpdateWindow( hwndPicture );
  614.          }
  615.  
  616.       return 0L;
  617.      }
  618.  
  619.  
  620. // Function: ProcessVertScroll - Process vertical scroll bar messages
  621. // --------------------------------------------------------------------
  622. // Parameters: HWND    hwndPicture       Handle of picture window
  623. //             WORD    wScrollCode       Scroll code as defined in windows.h
  624. //             int     nCurBoxPos        Current position of scroll box
  625. //
  626. // Returns:    LONG    0L if OK
  627. // --------------------------------------------------------------------
  628.    LONG FAR ProcessVertScroll
  629.                      (HWND hwndPicture, WORD wScrollCode, int nCurBoxPos )
  630.  
  631.      {NPPICTUREDATA   pPictureData;    // -> picture data struct
  632.       int             nPosition;       // Temp scroll position
  633.       WORD            wHeight;         // Picture height
  634.       int             nToScroll;       // Amount to scroll
  635.       RECT            rcPictArea;      // Picture rect in client coordinates
  636.  
  637.       if( !(pPictureData =
  638.                          (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  639.          {CommonTellUser( ViewerQueryResources(),
  640.                    VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  641.           return VIEWER_STRING_NOPICDATA;
  642.          }
  643.  
  644.       if( !IsWindowEnabled( pPictureData->spmsVScroll.hwnd ))
  645.           return 0L;
  646.  
  647.       nPosition = pPictureData->spmsVScroll.wCurPos;
  648.  
  649.       switch( wScrollCode )
  650.          {case SB_PAGEDOWN:
  651.               nPosition += pPictureData->spmsVScroll.wCurPage;
  652.               break;
  653.           case SB_LINEDOWN:
  654.               nPosition += pPictureData->spmsVScroll.wCurLine;
  655.               break;
  656.           case SB_PAGEUP:
  657.               nPosition -= pPictureData->spmsVScroll.wCurPage;
  658.               break;
  659.           case SB_LINEUP:
  660.               nPosition -= pPictureData->spmsVScroll.wCurLine;
  661.               break;
  662.           case SB_TOP:
  663.               nPosition = 0;
  664.               break;
  665.           case SB_BOTTOM:
  666.               nPosition = pPictureData->spmsVScroll.wCurMax;
  667.               break;
  668.           case SB_THUMBPOSITION:
  669.               nPosition = nCurBoxPos;
  670.               break;
  671.           default:
  672.               break;
  673.          }
  674.  
  675.       nPosition = min( max( 0, nPosition ),
  676.                                  (int) pPictureData->spmsVScroll.wCurMax );
  677.       if( nPosition != (int) pPictureData->spmsVScroll.wCurPos )
  678.          {nToScroll = nPosition - pPictureData->spmsVScroll.wCurPos;
  679.           pPictureData->spmsVScroll.wCurPos = nPosition;
  680.  
  681.           wHeight = pPictureData->rcCurPictureRect.bottom -
  682.                                        pPictureData->rcCurPictureRect.top;
  683.           pPictureData->rcCurPictureRect.top    = -nPosition;
  684.           pPictureData->rcCurPictureRect.bottom = -nPosition + wHeight;
  685.  
  686.           SetScrollPos( pPictureData->spmsVScroll.hwnd, SB_CTL,
  687.                                 pPictureData->spmsVScroll.wCurPos, TRUE );
  688.  
  689.             // Get picture rect in picture coordinates
  690.           GetClientRect( hwndPicture, &rcPictArea );
  691.           PictureRectFromClient( &rcPictArea);
  692.             // Convert to client coordinates for ScrollWindow
  693.           PictureToClient( (LPPOINT) &rcPictArea, 2 );
  694.  
  695.           if( ((WORD) abs( nToScroll )) <
  696.                                        pPictureData->spmsVScroll.wCurPage )
  697.              {UpdateWindow( hwndPicture );
  698.               ScrollWindow( hwndPicture, 0, -nToScroll,
  699.                                                 &rcPictArea, &rcPictArea );
  700.              }
  701.           else
  702.               InvalidateRect( hwndPicture, &rcPictArea, TRUE );
  703.  
  704.           UpdateWindow( hwndPicture );
  705.          }
  706.  
  707.       return 0L;
  708.      }
  709.  
  710. // Function: ScrollToCorner - Scroll to upper_left or lower-right corner
  711. // --------------------------------------------------------------------
  712. // Parameters: HWND    hwndPicture       Handle of picture window
  713. //             WORD    wScrollCode       Scroll code as defined in windows.h
  714. //
  715. // Returns:    LONG    0L if OK
  716. // --------------------------------------------------------------------
  717.    LONG FAR ScrollToCorner(HWND hwndPicture, WORD vk_key )
  718.  
  719.      {NPPICTUREDATA   pPictureData;    // -> picture data struct
  720.       int             nHorzPosition;   // Temp horz scroll position
  721.       int             nVertPosition;   // Temp vert scroll position
  722.       WORD            wWidth;          // Picture width
  723.       WORD            wHeight;         // Picture height
  724.       int             nHorzToScroll;   // Amount to scroll horz
  725.       int             nVertToScroll;   // Amount to scroll vert
  726.       RECT            rcPictArea;      // Picture rect in client coordinates
  727.  
  728.       if( !(pPictureData =
  729.                          (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  730.          {CommonTellUser( ViewerQueryResources(),
  731.                    VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  732.           return VIEWER_STRING_NOPICDATA;
  733.          }
  734.  
  735.       if( vk_key == VK_HOME )
  736.           nVertPosition = nHorzPosition = 0;
  737.       else
  738.          {nHorzPosition = pPictureData->spmsHScroll.wCurMax;          
  739.           nVertPosition = pPictureData->spmsVScroll.wCurMax;          
  740.          }
  741.  
  742.       nHorzToScroll = nHorzPosition - (int) pPictureData->spmsHScroll.wCurPos;
  743.       nVertToScroll = nVertPosition - (int) pPictureData->spmsVScroll.wCurPos;
  744.       if( nHorzToScroll || nVertToScroll )
  745.          {pPictureData->spmsHScroll.wCurPos = nHorzPosition;
  746.           pPictureData->spmsVScroll.wCurPos = nVertPosition;
  747.  
  748.           wWidth = pPictureData->rcCurPictureRect.right -
  749.                                        pPictureData->rcCurPictureRect.left;
  750.           pPictureData->rcCurPictureRect.left  = -nHorzPosition;
  751.           pPictureData->rcCurPictureRect.right = -nHorzPosition + wWidth;
  752.  
  753.           wHeight = pPictureData->rcCurPictureRect.bottom -
  754.                                        pPictureData->rcCurPictureRect.top;
  755.           pPictureData->rcCurPictureRect.top    = -nVertPosition;
  756.           pPictureData->rcCurPictureRect.bottom = -nVertPosition + wHeight;
  757.  
  758.           if( IsWindowEnabled( pPictureData->spmsHScroll.hwnd ))
  759.               SetScrollPos( pPictureData->spmsHScroll.hwnd, SB_CTL,
  760.                                 pPictureData->spmsHScroll.wCurPos, TRUE );
  761.           if( IsWindowEnabled( pPictureData->spmsVScroll.hwnd ))
  762.               SetScrollPos( pPictureData->spmsVScroll.hwnd, SB_CTL,
  763.                                 pPictureData->spmsVScroll.wCurPos, TRUE );
  764.  
  765.             // Get picture rect in picture coordinates
  766.           GetClientRect( hwndPicture, &rcPictArea );
  767.           PictureRectFromClient( &rcPictArea);
  768.             // Convert to client coordinates for ScrollWindow
  769.           PictureToClient( (LPPOINT) &rcPictArea, 2 );
  770.  
  771.           if( (((WORD) abs( nHorzToScroll )) <
  772.                            pPictureData->spmsHScroll.wCurPage ) &&
  773.                    (((WORD) abs( nVertToScroll )) <
  774.                                    pPictureData->spmsVScroll.wCurPage ))
  775.  
  776.              {UpdateWindow( hwndPicture );
  777.               ScrollWindow( hwndPicture, -nHorzToScroll, -nVertToScroll,
  778.                                                 &rcPictArea, &rcPictArea );
  779.              }
  780.           else
  781.               InvalidateRect( hwndPicture, &rcPictArea, TRUE );
  782.  
  783.           UpdateWindow( hwndPicture );
  784.          }
  785.  
  786.       return 0L;
  787.  
  788.      }
  789.  
  790.  
  791. // Function: IsInGrowBox - Determines if the cursor is in the grow box
  792. // --------------------------------------------------------------------
  793. // Parameters: HWND         hwndPicture       Handle of picture wnd
  794. //             POINT        ptCursor          Cursor position in client coords.
  795. //
  796. // Returns:    BOOL         TRUE if in grow box, else FALSE
  797. // --------------------------------------------------------------------
  798.    BOOL FAR IsInGrowBox( HWND hwndPicture, POINT ptCursor )
  799.  
  800.      {NPPICTUREDATA   pPictureData;    // -> picture data struct
  801.  
  802.       if( !(pPictureData =
  803.               (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )) ||
  804.                   !PtInRect( &pPictureData->rcGrowBox, ptCursor ))
  805.           return FALSE;
  806.       else
  807.           return TRUE;
  808.      }
  809.  
  810.  
  811. // Function: DestroyGrowBoxBitmap - Destroys the grow box bitnmap
  812. // --------------------------------------------------------------------
  813. // Parameters: VOID
  814. //
  815. // Returns:    VOID   
  816. // --------------------------------------------------------------------
  817.    VOID FAR DestroyGrowBoxBitmap( VOID )
  818.  
  819.      {if( g.hbmpGrowBox )
  820.         {DeleteObject( g.hbmpGrowBox );
  821.          g.hbmpGrowBox = NULL;
  822.         }
  823.  
  824.       return;
  825.      }
  826.  
  827.  
  828. // Function: PaintTheGrowBox - Paints the grow box
  829. // --------------------------------------------------------------------
  830. // Parameters: HWND             hwndPicture     Handle of picture window
  831. //             HDC              hdc             DC of picture window
  832. //             NPPICTUREDATA    pPictureData    -> picture wnd data struct
  833. //
  834. // Returns:    VOID   
  835. // --------------------------------------------------------------------
  836.    VOID FAR PaintTheGrowBox( HWND hwndPicture,
  837.                                  HDC hdc, NPPICTUREDATA pPictureData )
  838.  
  839.      {HDC        hmemDC;              // Memory dc
  840.       HBITMAP    hbmpSave;            // Prev bitmap
  841.       HBRUSH     hbrushSave;          // Background brush
  842.  
  843.       if( !g.hbmpGrowBox && 
  844.             !(g.hbmpGrowBox = GetGrowBoxBitmap( hdc, pPictureData )))
  845.           return;
  846.  
  847.       if( IsZoomed( hwndPicture ) && IsZoomed( ViewerQueryFrameWindow()))
  848.          {if( hbrushSave = SelectObject( hdc, GetStockObject( LTGRAY_BRUSH )))
  849.              {PatBlt( hdc,
  850.                   pPictureData->rcGrowBox.left,
  851.                   pPictureData->rcGrowBox.top,
  852.                   pPictureData->rcGrowBox.right - pPictureData->rcGrowBox.left,
  853.                   pPictureData->rcGrowBox.bottom - pPictureData->rcGrowBox.top,
  854.                   PATCOPY );
  855.  
  856.               SelectObject( hdc, hbrushSave );
  857.              }
  858.          }
  859.       else
  860.          {hmemDC = NULL;
  861.           if( ( hmemDC = CreateCompatibleDC( hdc )) &&
  862.                ( hbmpSave = SelectObject( hmemDC, g.hbmpGrowBox )))
  863.              {BitBlt( hdc, 
  864.                   pPictureData->rcGrowBox.left,
  865.                   pPictureData->rcGrowBox.top,
  866.                   pPictureData->rcGrowBox.right - pPictureData->rcGrowBox.left,
  867.                   pPictureData->rcGrowBox.bottom - pPictureData->rcGrowBox.top,
  868.                   hmemDC, 0, 0, SRCCOPY );
  869.  
  870.               SelectObject( hmemDC, hbmpSave );
  871.              }
  872.  
  873.           if( hmemDC )
  874.               DeleteDC( hmemDC );
  875.          }
  876.  
  877.       return;
  878.      }
  879.  
  880.  
  881. // Function: GetGrowBoxBitmap - Create the grow box mem bitmap. This routine
  882. //                              saves a bitmap of the correct size so that
  883. //                              bitblt can be used to draw the bitmap instead
  884. //                              stetchblt which is much slower
  885. // --------------------------------------------------------------------
  886. // Parameters: HDC              hdc             DC of picture window
  887. //             NPPICTUREDATA    pPictureData    -> picture wnd data struct
  888. //
  889. // Returns:    HBITMAP          hbmpGrowBox     Handle of grow box mem bitmap   
  890. // --------------------------------------------------------------------
  891.    static HBITMAP NEAR GetGrowBoxBitmap( HDC hdc, NPPICTUREDATA pPictureData )
  892.  
  893.      {HDC               hmemDC1;          // Mem dc
  894.       HDC               hmemDC2;          // Mem dc
  895.       BITMAP            bm;               // bitmap struct
  896.       HBITMAP           hbmp;             // Handle of resource bitmap
  897.       HBITMAP           hbmpSave1;        // Prev bitmap
  898.       HBITMAP           hbmpSave2;        // Prev bitmap
  899.       HBITMAP           hbmpGrowBox;      // Handle of grow box bitmap
  900.       int               nWidth;           // Width of final bitmap
  901.       int               nHeight;          // Height of final bitmap
  902.       HBRUSH            hbrushSave;       // Prev brush
  903.       int               xOffset;          // x bitmap offset
  904.       int               yOffset;          // y bitmap offset
  905.  
  906.  
  907.       if( !( hbmp = LoadBitmap( ViewerQueryResources(), 
  908.                             MAKEINTRESOURCE( VIEWER_GROWBOX_BITMAP ))))
  909.           return NULL;
  910.  
  911.       hmemDC1 = hmemDC2 = NULL;
  912.       nWidth  = pPictureData->rcGrowBox.right - pPictureData->rcGrowBox.left;
  913.       nHeight = pPictureData->rcGrowBox.bottom - pPictureData->rcGrowBox.top;
  914.  
  915.       if( ( hmemDC1 = CreateCompatibleDC( hdc )) &&
  916.              ( hmemDC2 = CreateCompatibleDC( hdc )) &&
  917.                  ( hbmpGrowBox = CreateCompatibleBitmap
  918.                                                  ( hdc, nWidth, nHeight )))
  919.          {hbmpSave1 = SelectObject( hmemDC1, hbmp ); 
  920.           hbmpSave2 = SelectObject( hmemDC2, hbmpGrowBox );
  921.  
  922.              // set the background to light gray
  923.           hbrushSave = SelectObject( hmemDC2, GetStockObject( LTGRAY_BRUSH ));
  924.           PatBlt( hmemDC2, 0, 0, nWidth, nHeight, PATCOPY );
  925.           SelectObject( hmemDC2, hbrushSave );
  926.  
  927.           GetObject( hbmp, sizeof( BITMAP ), &bm );
  928.           xOffset = ( nWidth - bm.bmWidth ) / 2;
  929.           yOffset = ( nHeight - bm.bmHeight ) / 2;
  930.  
  931.           BitBlt( hmemDC2, max( 0, xOffset ), max( 0, yOffset ),
  932.                       min( bm.bmWidth, nWidth ),
  933.                       min( bm.bmHeight, nHeight ),
  934.                       hmemDC1, 
  935.                       max( 0, -xOffset ),
  936.                       max( 0, -yOffset ), SRCCOPY );
  937.  
  938.           SelectObject( hmemDC1, hbmpSave1 ); 
  939.           SelectObject( hmemDC2, hbmpSave2 );
  940.          }
  941.  
  942.       if( hmemDC1 )
  943.           DeleteDC( hmemDC1 );
  944.       if( hmemDC2 )
  945.           DeleteDC( hmemDC2 );
  946.  
  947.       DeleteObject( hbmp );
  948.      
  949.       return hbmpGrowBox;
  950.      }
  951.  
  952.  
  953. // Function: LimitTheDragSize - Limits the resized of the window so that it stays 
  954. //                              inside the MDI client rect. Used with grow box
  955. //                              processing
  956. // --------------------------------------------------------------------
  957. // Parameters: HWND             hwndPicture     hwnd of picture window
  958. //             BOOL             bDragging       TRUE if dragging using grow box
  959. //
  960. // Returns:    VOID   
  961. // --------------------------------------------------------------------
  962.    VOID FAR LimitTheDragSize( HWND hwndPicture, BOOL bDragging )
  963.  
  964.      {RECT   rcClient;          // Client rect of MDI client
  965.       RECT   rcwndPicture;      // Window rect of picture wnd
  966.  
  967.       if( !( g.bLimitGrowBoxResize = bDragging ))
  968.           return;
  969.  
  970.       if( !IsZoomed( hwndPicture ))
  971.          {GetWindowRect( hwndPicture, &rcwndPicture );
  972.           GetClientRect( ViewerQueryClientWindow(), &rcClient );
  973.  
  974.           MapWindowPoints( HWND_DESKTOP, ViewerQueryClientWindow(), 
  975.                                      (LPPOINT) &rcwndPicture, 2 );
  976.  
  977.           g.ptMaxGrowBoxResize.x = rcClient.right - rcwndPicture.left;
  978.           g.ptMaxGrowBoxResize.y = rcClient.bottom - rcwndPicture.top;
  979.          }
  980.  
  981.       return;
  982.      }
  983.  
  984.  
  985. // Function: InitMaxWndGrowBoxResize - Initializes the maximized window grow
  986. //                                     box resizing
  987. // --------------------------------------------------------------------
  988. // Parameters: HWND        hwndPicture    Handle of picture wnd
  989. //             POINT       ptCursor       Position of cursor
  990. //
  991. // Returns:    BOOL        TRUE if successful
  992. // --------------------------------------------------------------------
  993.    BOOL FAR InitMaxWndGrowBoxResize( HWND hwndPicture, POINT ptCursor )
  994.  
  995.      {RECT         rcClipCursor;      // Clip cursor rect
  996.       HDC          hdc;               // DC of desktop
  997.  
  998.  
  999.       GetWindowRect( ViewerQueryFrameWindow(), &g.rcResizeRect );
  1000.       ClientToScreen( hwndPicture, &ptCursor );
  1001.       g.ptCursorOffset.x = g.rcResizeRect.right  - ptCursor.x;
  1002.       g.ptCursorOffset.y = g.rcResizeRect.bottom - ptCursor.y;
  1003.  
  1004.       rcClipCursor.left = g.rcResizeRect.left + 
  1005.                GetSystemMetrics( SM_CXMINTRACK ) - g.ptCursorOffset.x;
  1006.       rcClipCursor.top  = g.rcResizeRect.top +
  1007.                GetSystemMetrics( SM_CYMINTRACK ) - g.ptCursorOffset.y;
  1008.  
  1009.       if( hdc = GetDC( NULL ))
  1010.          {rcClipCursor.right =
  1011.                   GetDeviceCaps( hdc, HORZRES ) - g.ptCursorOffset.x;
  1012.           rcClipCursor.bottom = 
  1013.                   GetDeviceCaps( hdc, VERTRES ) - g.ptCursorOffset.y;
  1014.           ReleaseDC( NULL, hdc );
  1015.          }
  1016.        else
  1017.          {rcClipCursor.right  = 0x7fff;
  1018.           rcClipCursor.bottom = 0x7fff;
  1019.          }
  1020.       ClipCursor( &rcClipCursor );
  1021.  
  1022.       DrawTheFrameRect( &g.rcResizeRect );
  1023.  
  1024.       return TRUE;
  1025.      }
  1026.  
  1027.  
  1028. // Function: MoveTheFrameRect - Moves the resizing rect during maximized 
  1029. //                              window grow box resizing
  1030. // --------------------------------------------------------------------
  1031. // Parameters: HWND        hwndPicture    Handle of picture wnd
  1032. //             POINT       ptCursor       Position of cursor
  1033. //
  1034. // Returns:    VOID
  1035. // --------------------------------------------------------------------
  1036.    VOID FAR MoveTheFrameRect( HWND hwndPicture, POINT ptCursor )
  1037.  
  1038.      {DrawTheFrameRect( &g.rcResizeRect );
  1039.  
  1040.       ClientToScreen( hwndPicture, &ptCursor );
  1041.       g.rcResizeRect.right  = ptCursor.x + g.ptCursorOffset.x;
  1042.       g.rcResizeRect.bottom = ptCursor.y + g.ptCursorOffset.y;
  1043.  
  1044.       DrawTheFrameRect( &g.rcResizeRect );
  1045.  
  1046.       return;
  1047.      }
  1048.  
  1049.  
  1050. // Function: EndMaxWndGrowBoxResize - Terminates the maximized window grow
  1051. //                                    box resizing
  1052. // --------------------------------------------------------------------
  1053. // Parameters: HWND        hwndPicture    Handle of picture wnd
  1054. //
  1055. // Returns:    VOID
  1056. // --------------------------------------------------------------------
  1057.    VOID FAR EndMaxWndGrowBoxResize( HWND hwndPicture )
  1058.  
  1059.      {DrawTheFrameRect( &g.rcResizeRect );
  1060.       DrawTheFrameRect( NULL );             // Does clean up
  1061.  
  1062.       ClipCursor( NULL );
  1063.       MoveWindow( ViewerQueryFrameWindow(),
  1064.                    g.rcResizeRect.left, g.rcResizeRect.top,
  1065.                    g.rcResizeRect.right - g.rcResizeRect.left,
  1066.                    g.rcResizeRect.bottom - g.rcResizeRect.top, TRUE );
  1067.  
  1068.       return;
  1069.      }
  1070.  
  1071.  
  1072. // Function: DrawTheFrameRect - Draws the resizing frame
  1073. // --------------------------------------------------------------------
  1074. // Parameters: RECT      lprcResizeRect     -> resize rect
  1075. //
  1076. // Returns:    VOID 
  1077. // --------------------------------------------------------------------
  1078.    static VOID NEAR DrawTheFrameRect( LPRECT lprcResizeRect )
  1079.  
  1080.      {HDC            hdc;               // DC of desktop
  1081.       HBRUSH         hbrushSave;        // Prev brush
  1082.       HBITMAP        hbitmapCheckers;   // Handle of checkerboard bitmap
  1083.  
  1084. typedef  BOOL ( CALLBACK* FFRAMEPROC ) (HDC, LPRECT, int, int, DWORD);
  1085.  
  1086.       static  WORD   wBorderWidth;      // Width of vertical resize border
  1087.       static  WORD   wBorderHeight;     // Height of horizontal resize border
  1088.       static  FFRAMEPROC  lpfnFastWindowFrame;   // -> FastWindowFrame()
  1089.       static  HBRUSH  hbrushCheckers;   // Handle to frame brush
  1090.  
  1091.  
  1092.          // FastWindowFrame() is an undocumented Windows function
  1093.          // described in "Undocumented Windows" by Andrew Schulman,
  1094.          // David Maxey and Matt Pietrek, Addison Wesley, 1992.
  1095.  
  1096.       if( lprcResizeRect == NULL )    // Clean up 
  1097.          {if( hbrushCheckers )
  1098.              {DeleteObject( hbrushCheckers );
  1099.               hbrushCheckers = NULL;
  1100.              }
  1101.           return;
  1102.          }
  1103.  
  1104.       if( !lpfnFastWindowFrame )
  1105.          {lpfnFastWindowFrame = (FFRAMEPROC) GetProcAddress( 
  1106.                             GetModuleHandle( "GDI" ), "FASTWINDOWFRAME" );
  1107.           wBorderWidth  = GetSystemMetrics( SM_CXFRAME ) - 1;
  1108.           wBorderHeight = GetSystemMetrics( SM_CXFRAME ) - 1;
  1109.          }
  1110.  
  1111.       if( !hbrushCheckers &&
  1112.            ( hbitmapCheckers = LoadBitmap( ViewerQueryInstance(),
  1113.                            MAKEINTRESOURCE( VIEWER_CHECKERS_BITMAP ))))
  1114.          {hbrushCheckers = CreatePatternBrush( hbitmapCheckers );
  1115.           DeleteObject( hbitmapCheckers );
  1116.          }
  1117.  
  1118.       if( hdc = GetDC( NULL ))
  1119.          {if( lpfnFastWindowFrame )
  1120.              {
  1121.               if( hbrushCheckers )
  1122.                   hbrushSave = SelectObject( hdc, hbrushCheckers );
  1123.               else
  1124.                   hbrushSave = SelectObject( hdc,
  1125.                                          GetStockObject( GRAY_BRUSH ));
  1126.               
  1127.               if( !( *lpfnFastWindowFrame ) ( hdc, lprcResizeRect, 
  1128.                                     wBorderWidth, wBorderHeight, PATINVERT ))
  1129.                  {  // Use PatBlt when FastWindowFrame fails
  1130.                   ExcludeClipRect( hdc,
  1131.                                 lprcResizeRect->left + wBorderWidth,
  1132.                                 lprcResizeRect->top  + wBorderHeight,
  1133.                                 lprcResizeRect->right  - wBorderWidth,
  1134.                                 lprcResizeRect->bottom - wBorderHeight );
  1135.  
  1136.                   PatBlt( hdc, lprcResizeRect->left,
  1137.                                lprcResizeRect->top,
  1138.                                lprcResizeRect->right - lprcResizeRect->left,
  1139.                                lprcResizeRect->bottom - lprcResizeRect->top,
  1140.                                PATINVERT );
  1141.                  }
  1142.  
  1143.               if( hbrushSave )
  1144.                   SelectObject( hdc, hbrushSave );
  1145.              }
  1146.           else
  1147.              {DrawFocusRect( hdc, lprcResizeRect ); 
  1148.              }
  1149.  
  1150.           ReleaseDC( NULL, hdc );
  1151.          }
  1152.  
  1153.       return;
  1154.      }
  1155.  
  1156.  
  1157. // Function: PictureBannerWndProc - Window proc for the banner child window
  1158. // --------------------------------------------------------------------
  1159. // Parameters: As required by Microsoft Windows
  1160. //
  1161. // Returns:    Via DefWindowProc
  1162. // --------------------------------------------------------------------
  1163.    LONG __export CALLBACK PictureBannerWndProc
  1164.              (HWND hwndBanner, UINT message, WPARAM wParam, LPARAM lParam)
  1165.  
  1166.      {NPPICTUREDATA  pPictureData;     // -> picture data struct
  1167.       PAINTSTRUCT    ps;               // Paint struct
  1168.       RECT           rcClient;         // Client rect of control
  1169.       UINT           nSaveAlign;       // Prev text align
  1170.       WORD           wBaseLine;        // Base line for text output
  1171.       HFONT          hFont;            // Handle of font
  1172.       HFONT          hsaveFont;        // Handle of prev font
  1173.       int            nHeight;          // Height of font
  1174.  
  1175.  
  1176.       if( message == WM_PAINT )
  1177.          {if( !(pPictureData = (NPPICTUREDATA) GetWindowWord
  1178.                                          ( GetParent( hwndBanner ), 0 )))
  1179.               return 0L;
  1180.  
  1181.           if( !BeginPaint( hwndBanner, &ps ))
  1182.               return 0L;
  1183.  
  1184.           GetClientRect( hwndBanner, &rcClient );
  1185.           MoveTo( ps.hdc, 0, rcClient.bottom - 1 );
  1186.           LineTo( ps.hdc, rcClient.right, rcClient.bottom - 1 );
  1187.  
  1188.             // Don't report an error if this fails since it will just
  1189.             // use the system font instead
  1190.           nHeight = -MulDiv( BANNER_TEXT_HEIGHT,
  1191.                             GetDeviceCaps( ps.hdc, LOGPIXELSY ), 72 );
  1192.           hsaveFont = NULL;
  1193.           if( hFont = MakeAnArialFont( ps.hdc, nHeight ))
  1194.              hsaveFont = SelectObject( ps.hdc, hFont );
  1195.  
  1196.           wBaseLine = 3 * rcClient.bottom / 4;
  1197.           nSaveAlign = SetTextAlign( ps.hdc, TA_LEFT | TA_BASELINE );
  1198.           TextOut( ps.hdc, 6, wBaseLine, pPictureData->szPictType,
  1199.                                      lstrlen( pPictureData->szPictType ));
  1200.  
  1201.           SetTextAlign( ps.hdc, TA_RIGHT | TA_BASELINE );
  1202.           SetTextCharacterExtra( ps.hdc, 
  1203.                  GetTextCharacterExtra( ps.hdc ) + TEXT_EXTRA_SPACING );
  1204.  
  1205.           TextOut( ps.hdc, rcClient.right - 6, wBaseLine,
  1206.                                 pPictureData->szFileSize,
  1207.                                      lstrlen( pPictureData->szFileSize ));
  1208.  
  1209.           SetTextAlign( ps.hdc, nSaveAlign );
  1210.  
  1211.           if( hsaveFont )
  1212.              SelectObject( ps.hdc, hsaveFont ); 
  1213.           if( hFont )
  1214.              DeleteObject( hFont ); 
  1215.  
  1216.           EndPaint( hwndBanner, &ps );
  1217.           return 0L;
  1218.          }
  1219.       else
  1220.          return DefWindowProc( hwndBanner, message, wParam, lParam);
  1221.      }
  1222.  
  1223.  
  1224. // Function: MakeAnArialFont - Creates a logical font
  1225. // --------------------------------------------------------------------
  1226. // Parameters: HDC           hdc              Device context
  1227. //             int           nTextSize        Size of font
  1228. //
  1229. // Returns:    HFONT         hFont
  1230. //           Note: It is up to the caller to eventually delete this font
  1231. // --------------------------------------------------------------------
  1232.    HFONT FAR MakeAnArialFont( HDC hdc, int nTextSize )
  1233.  
  1234.      {HFONT       hFont;         // Handle to created font
  1235.       PLOGFONT    plf;           // -> to font struct
  1236.  
  1237.       if( !( plf = (PLOGFONT) LocalAlloc( LPTR, sizeof( LOGFONT ))))
  1238.           return NULL;
  1239.  
  1240.       plf->lfHeight         = nTextSize;
  1241.       plf->lfWeight         = FW_LIGHT;
  1242.       plf->lfOutPrecision   = OUT_TT_ONLY_PRECIS;
  1243.       plf->lfPitchAndFamily = FF_SWISS;
  1244.       LoadString( ViewerQueryResources(), VIEWER_STRING_FACENAME, 
  1245.                            plf->lfFaceName, sizeof( plf->lfFaceName ));
  1246.  
  1247.       hFont = CreateFontIndirect( plf );
  1248.  
  1249.       LocalFree( (LOCALHANDLE) plf );
  1250.  
  1251.       return hFont;
  1252.      }
  1253.  
  1254.  
  1255. // Function: RegisterChildControls - Registers the window classes for the
  1256. //                                   picture resizing and banner child windows
  1257. // --------------------------------------------------------------------
  1258. // Parameters: HINSTANCE     hInstance  Instance of application
  1259. //
  1260. // Returns:    BOOL          TRUE if OK
  1261. // --------------------------------------------------------------------
  1262.    BOOL FAR RegisterChildControls( HINSTANCE hInstance )
  1263.  
  1264.      {WNDCLASS     wc;   // Window class information
  1265.  
  1266.       wc.style         = CS_HREDRAW | CS_VREDRAW;
  1267.       wc.lpfnWndProc   = PictureZoomWndProc;
  1268.       wc.cbClsExtra    = 0;
  1269.       wc.cbWndExtra    = 0;
  1270.       wc.hInstance     = hInstance;
  1271.       wc.hIcon         = NULL;
  1272.       wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
  1273.       wc.hbrBackground = (HBRUSH) ( COLOR_BTNFACE + 1 );
  1274.       wc.lpszMenuName  = NULL;
  1275.       wc.lpszClassName = PICTURE_ZOOM_CLASS;
  1276.  
  1277.       if( !RegisterClass( &wc ))
  1278.           return FALSE;
  1279.  
  1280.       wc.style         = CS_HREDRAW | CS_VREDRAW;
  1281.       wc.lpfnWndProc   = PictureBannerWndProc;
  1282.       wc.cbClsExtra    = 0;
  1283.       wc.cbWndExtra    = 0;
  1284.       wc.hInstance     = hInstance;
  1285.       wc.hIcon         = NULL;
  1286.       wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
  1287.       wc.hbrBackground = GetStockObject( WHITE_BRUSH );
  1288.       wc.lpszMenuName  = NULL;
  1289.       wc.lpszClassName = PICTURE_BANNER_CLASS;
  1290.  
  1291.       return RegisterClass( &wc );
  1292.      }
  1293.